// Copyright (c) 2021 Presto Labs Pte. Ltd.
// Author: hyuan

#pragma once

#include <memory>
#include <string>
#include <unordered_map>

#include "coin2/exchange/base/order/order.h"
#include "coin2/exchange/order/phemex.pb.h"
#include "coin2/exchange/phemex_base/api_util/auth_key.h"
#include "coin2/exchange/phemex_base/api_util/rate_tracker.h"

namespace coin2::exchange::phemex::api_order {

enum PhemexOrderSubTopicId : int {
  REST_DEPOSIT = 10000,
  REST_WITHDRAWAL = 10001,
  TRANSFER_SPOT = 10002,
  TRANSFER_FUTURES = 10003
};

}  // namespace coin2::exchange::phemex::api_order

class PhemexNativePrivateClient : public coin2::exchange::base::order::NativePrivateClient {
 public:
  using PhemexRateTracker = coin2::exchange::phemex::api_util::PhemexRateTracker;
  using RestParams = coin2::exchange::order::PhemexRestParams;
  using NativeClientConfig = coin2::exchange::order::OrderConnectionConfig;
  using RestQueryProto = coin2::exchange::base::order::RestQueryProto;
  using PhemexOrderSubTopicId = coin2::exchange::phemex::api_order::PhemexOrderSubTopicId;
  using AsioHttpContextList = std::list<std::shared_ptr<AsioHttpContext>>;

 public:
  explicit PhemexNativePrivateClient(
      const MarketExchangeApi& mea,
      const NativeClientConfig& config);

  std::shared_ptr<AsioHttpContext> QueryAccountBalance(const RestParams& params);
  std::shared_ptr<AsioHttpContext> QueryOpenOrders(const RestParams& params);
  std::shared_ptr<AsioHttpContext> QueryHistoryOrders(const RestParams& params);
  std::shared_ptr<AsioHttpContext> QueryFills(const RestParams& params);
  std::shared_ptr<AsioHttpContext> QueryDeposit(const RestParams& params);
  std::shared_ptr<AsioHttpContext> QueryWithdraw(const RestParams& params);
  std::shared_ptr<AsioHttpContext> QuerySpotAccountTransfer(const RestParams& params);
  std::shared_ptr<AsioHttpContext> QueryFuturesAccountTransfer(const RestParams& params);

  std::shared_ptr<AsioHttpContext> PlaceOrder(const RestParams& params);
  std::shared_ptr<AsioHttpContext> CancelOrder(const RestParams& params);
  std::shared_ptr<AsioHttpContext> PlaceOrderNorm(const OrderExecution&) override;
  std::shared_ptr<AsioHttpContext> CancelOrderNorm(const OrderExecution&) override;
  std::shared_ptr<AsioHttpContext> SubmitOrderExecution(const OrderExecutionProto& order) override;
  std::shared_ptr<AsioHttpContext> SubmitRestQuery(const RestQueryProto& query) override;
  void Prepare();

  RestParams GetRestOrderParams(const OrderSpec& order_spec, int64_t proc_order_id);
  RestParams GetRestCancelParams(const IOrderContext& order_context);

  std::string DebugString() const;

  std::string GetUserId() { return user_id; }

  AsioHttpContextList SubmitRestQueryList(const RestQueryProto& query);

  const std::vector<std::string>& GetTransferCurrencyList() {
    const static std::vector<std::string> currency_list =
        {"CCX", "USDT", "BTC", "ETH", "CFX", "USDC", "BUSD", "JOY"};
    return currency_list;
  }

 private:
  std::string user_id;
  int64_t start_time_;
  PhemexRateTracker* local_rate_tracker_;
  std::unordered_map<std::string, int32_t> api_block_info_;
  std::unordered_map<std::string, int32_t> api_req_info_;
};
